﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;

namespace StuMana.Services
{
    /**
     * Moi mot lop SL025M quản lí một cổng COM để truyền nhận data. va control 1 database de update data.
     * trong do no cung control 1 timer dung de doc tu dong neu can thiet.
     */
public    class SL025M
    {


        public SerialPort conn = new SerialPort();
        private byte[] write_data = new byte[16];

        int _sector = 2;
        int _block = 0;// _block = 0;
        public byte[] serial_buffer = new byte[1000];

        public const byte mode_send = 2;
        public const byte mode_recive = 1;
        public const byte Header = 0xBA;
        public const byte Header_rec = 0xBD;
        public const byte Select_Card = 0x01;
        public const byte Login = 0x02;
        public const byte Read_data_block = 0x03;
        public const byte Write_data_block = 0x04;
        public const byte Read_value_block = 0x05;
        public const byte Write_value_block = 0x06;
        public const byte Write_master_keyA = 0x07;
        public const byte Increment = 0x08;
        public const byte Decrement = 0x09;
        public const byte Copy = 0x0A;
        public const byte Read_data_page = 0x10;
        public const byte Write_data_page = 0x11;
        public const byte Control_led = 0x40;
        public const byte Reset = 0xFF;

        public  SL025M()
        {
        }

        public void selectCard()
        {
            protocal(Select_Card, null);
        }
        public void LogIn()
        {
            byte[] dat_login = new byte[10];

                dat_login[0] = 0xAA;         


                dat_login[1] = str_to_byte("FF");
                dat_login[2] = str_to_byte("FF");
                dat_login[3] = str_to_byte("FF");
                dat_login[4] = str_to_byte("FF");
                dat_login[5] = str_to_byte("FF");
                dat_login[6] = str_to_byte("FF");
                protocal(Login, dat_login);

        }
        public Boolean bt_write(int tagID, int account)
        {
            byte[] ID_byteArray = new byte[3];
            byte[] acc_byteArray = new byte[4];
            byte[] dat_write = new byte[20];
            int cal_block = 0;
            try
            {
                cal_block = _block + (_sector * 4);
                dat_write[0] = Convert.ToByte(cal_block);
            }
            catch
            {
                MessageBox.Show("Error Block");
            }
            
            ID_byteArray = BitConverter.GetBytes(tagID);
            acc_byteArray = BitConverter.GetBytes(account);

            for (int i = 0; i < 19; i++)
            {
                dat_write[i+1] = 0;
            }

            for (int i = 0; i < 3; i++)
            {
                dat_write[i + 1] = ID_byteArray[i];
                
            }
            for (int i = 0; i < 4; i++)
            {
                dat_write[i + 4] = acc_byteArray[i];

            }
            
            protocal(Write_data_block, dat_write);
            
            return true;               
            /*
            {
                byte[] byteArray = BitConverter.GetBytes(tagID);
                string temp = "";
                for (int i = 0; i < byteArray.Length; i++)
                {
                    write_data[i]=byteArray[i];
                    temp += byteArray[i] + " ";
                }
                MessageBox.Show(temp);
                protocal(Write_data_block, write_data);
            }
             */
        }
        public void ReadData()
        {
             protocal(Read_data_block, null);
        }
        public void get_connect(COM connect)
        {
            conn = connect.connecting();
        }
        public void disconnect(COM connect)
        {
           connect.closeCOMPort();
        }
        void protocal(byte cmd, byte[] data)
        {
            byte[] send_byte = new byte[30];
            send_byte[0] = Header;
            int temp_sector = 0;
            int sector = 0, block = 0;
            sector = _sector;
            block = _block;
            temp_sector = block + (sector * 4);


            switch (cmd)
            {
                case Select_Card:

                    send_byte[1] = 2;
                    send_byte[2] = Select_Card;
                    send_byte[3] = cal_chk(send_byte, mode_send);
                    send_out_(send_byte);
                    break;
                case Login:

                    send_byte[1] = 10;
                    send_byte[2] = Login;
                    send_byte[3] = byte.Parse(_sector.ToString());
                    for (int i = 0; i < send_byte[1] - 3; i++)
                    {
                        send_byte[4 + i] = data[i];
                    }
                    send_byte[11] = cal_chk(send_byte, mode_send);
                    send_out_(send_byte);
                    break;
                case Read_data_block:
                    send_byte[1] = 3;
                    send_byte[2] = Read_data_block;
                    send_byte[3] = Convert.ToByte(temp_sector);
                    send_byte[4] = cal_chk(send_byte, mode_send);
                   // MessageBox.Show("Chuoi can ghi: " + BitConverter.ToString(send_byte));
                    send_out_(send_byte);
                    break;
                case Write_data_block:
                    send_byte[1] = 19;
                    send_byte[2] = Write_data_block;
                    for (int cnt = 0; cnt <= 16; cnt++)
                    {
                        send_byte[3 + cnt] = data[cnt];
                    }
                    send_byte[20] = cal_chk(send_byte, mode_send);
                    send_out_(send_byte);
                    break;
                case Read_value_block:

                    send_byte[1] = 3;
                    send_byte[2] = Read_value_block;
                    send_byte[3] = Convert.ToByte(temp_sector);
                    send_byte[4] = cal_chk(send_byte, mode_send);
              //      MessageBox.Show("chuoi ghi vao tag" + BitConverter.ToString(send_byte));
                    MessageBox.Show("ghi vao tag thanh cong: " + BitConverter.ToString(send_byte));
                    send_out_(send_byte);
                    break;
                case Write_value_block:
                    send_byte[1] = 7;
                    send_byte[2] = Write_value_block;
                    for (int cnt = 0; cnt <= 5; cnt++)
                    {
                        send_byte[3 + cnt] = data[cnt];
                    }
                    send_byte[8] = cal_chk(send_byte, mode_send);
                    send_out_(send_byte);
                    break;
                case Increment:
                    send_byte[1] = 7;
                    send_byte[2] = Increment;
                    for (int cnt = 0; cnt <= 5; cnt++)
                    {
                        send_byte[3 + cnt] = data[cnt];
                    }
                    send_byte[8] = cal_chk(send_byte, mode_send);
                    send_out_(send_byte);
                    break;
                case Decrement:
                    send_byte[1] = 7;
                    send_byte[2] = Decrement;
                    for (int cnt = 0; cnt <= 5; cnt++)
                    {
                        send_byte[3 + cnt] = data[cnt];
                    }
                    send_byte[8] = cal_chk(send_byte, mode_send);
                    send_out_(send_byte);
                    break;
                case Control_led:
                    send_byte[1] = 3;
                    send_byte[2] = Control_led;
                    send_byte[3] = data[0];
                    send_byte[4] = cal_chk(send_byte, mode_send);
                    send_out_(send_byte);
                    break;
                case Write_master_keyA:
                    send_byte[1] = 9;
                    send_byte[2] = Write_master_keyA;
                    for (int i = 0; i < send_byte[1] - 2; i++)
                    {
                        send_byte[3 + i] = data[i];
                    }
                    send_byte[10] = cal_chk(send_byte, mode_send);
                    send_out_(send_byte);
                    break;
            }
        }
        void send_out_(byte[] out_)
        {           
            conn.Write(out_, 0, out_[1] + 2);
           // MessageBox.Show("Chuoi can ghi: " + BitConverter.ToString(out_));
        }
        byte cal_chk(byte[] cal_sum, int mode)
        {
            Int32 chk = 0;
            if (mode == mode_send)
                chk = Header;
            else
                chk = Header_rec;

            for (int cnt = 1; cnt < cal_sum[1] + mode; cnt++)
            {
                chk = chk ^ cal_sum[cnt];
            }
            return Convert.ToByte(chk);
        }
        byte str_to_byte(string str_key)
        {
            char[] data = str_key.ToCharArray();
            int len = data.Length;
            int[] num = new Int32[len];
            int fg = 1;

            for (int i = 0; i < len; i++)
            {
                if ((data[i] >= '0') || (data[i] <= '9'))
                {
                    num[i] = (Convert.ToInt32(data[i])) - 0x30;

                }
                if ((data[i] >= 'A') || (data[i] <= 'F'))
                {
                    switch (data[i])
                    {
                        case 'A':
                            num[i] = 10;
                            break;
                        case 'B':
                            num[i] = 11;
                            break;
                        case 'C':
                            num[i] = 12;
                            break;
                        case 'D':
                            num[i] = 13;
                            break;
                        case 'E':
                            num[i] = 14;
                            break;
                        case 'F':
                            num[i] = 15;
                            break;
                    }
                }
            }
            for (int i = 0; i < len; i++)
            {
                if ((num[i] > 15) || (num[i] < 0))
                {
                    MessageBox.Show("Please Key HEX");
                    fg = 0;
                }
            }
            if (fg == 1)
            {
                return _to_byte(num)[0];
            }
            return 0;
        }

        byte[] _to_byte(int[] in_byte)
        {

            int len = in_byte.Length;

            byte[] _byte_buf = new byte[len / 2];
            byte a;
            int j = 0;

            for (int i = 0; i < len / 2; i++)
            {
                a = Convert.ToByte(in_byte[j] << 4);
                j++;
                a |= Convert.ToByte(in_byte[j]);
                j++;
                _byte_buf[i] = a;

            }
            return _byte_buf;
        }

        // lay chuoi tra ve
        public void get_serial(byte[] serial,int count)
        {
            for (int i = 0; i < count; i++)
            {
                 serial_buffer[i] = serial[i];
            }
            string temp = "";
            for (int i = 0; i < serial_buffer.Length; i++)
            {
                temp += serial_buffer[i].ToString() + "  ";
            }
            MessageBox.Show("Receive: " + temp);
        }

    }
}
